/*
 * font.cpp
 *
 *  Created on: 22/12/2008
 *      Author: smaxll
 */

#include "font.hpp"

#include <map>
#include <vector>

namespace {

    //cache sizes of small text
    typedef std::map<std::string,SDL_Rect> line_size_cache_map;

    //map of styles -> sizes -> cache
    std::map<int,std::map<int,line_size_cache_map> > line_size_cache;

}

namespace font {

const SDL_Color NORMAL_COLOUR = {0xDD,0xDD,0xDD,0},
                GRAY_COLOUR   = {0x77,0x77,0x77,0},
                LOBBY_COLOUR  = {0xBB,0xBB,0xBB,0},
                GOOD_COLOUR   = {0x00,0xFF,0x00,0},
                BAD_COLOUR    = {0xFF,0x00,0x00,0},
                BLACK_COLOUR  = {0x00,0x00,0x00,0},
                YELLOW_COLOUR = {0xFF,0xFF,0x00,0},
                BUTTON_COLOUR = {0xBC,0xB0,0x88,0},
                STONED_COLOUR = {0xA0,0xA0,0xA0,0},
                TITLE_COLOUR  = {0xBC,0xB0,0x88,0},
                LABEL_COLOUR  = {0x6B,0x8C,0xFF,0},
                BIGMAP_COLOUR = {0xFF,0xFF,0xFF,0};
//const SDL_Color DISABLED_COLOUR = inverse(STONED_COLOUR);

}


namespace font {

namespace {
static const size_t max_text_line_width = 4096;

class text_surface {
public:
    text_surface(std::string const &str, int size, SDL_Color color, int style);
    text_surface(int size, SDL_Color color, int style);

    std::vector<SDL_Surface> const & get_surfaces() const;

    size_t width() const;
    size_t height() const;

private:
    int hash_;
    int font_size_;
    SDL_Color color_;
    int style_;
    mutable int w_, h_;
    std::string str_;
    mutable bool initialized_;
//    mutable std::vector<text_chunk> chunks_;
    mutable std::vector<SDL_Surface> surfs_;

    void hash();
};

text_surface::text_surface(std::string const &str, int size, SDL_Color color, int style)
    : font_size_(size),
    color_(color),
    style_(style),
    w_(-1),
    h_(-1),
    str_(str),
    initialized_(false)
{
    hash();
}

void text_surface::hash(){
    int h = 0;
    for(std::string::const_iterator it = str_.begin(), it_end = str_.end(); it != it_end; ++it)
        h = ((h << 9) | (h >> (sizeof(int) * 8 - 9))) ^ (*it);
    hash_ = h;
}

size_t text_surface::width() const
{
    if (w_ == -1) {
//        if(chunks_.empty())
//            chunks_ = split_text(str_);
//        measure();
    }
    return w_;
}

size_t text_surface::height() const
{
    if (h_ == -1) {
//        if(chunks_.empty())
//            chunks_ = split_text(str_);
//        measure();
    }
    return h_;
}

}



SDL_Rect line_size(const std::string& line, int font_size, int style)
{
    line_size_cache_map& cache = line_size_cache[style][font_size];

    const line_size_cache_map::const_iterator i = cache.find(line);
    if(i != cache.end()) {
        return i->second;
    }

    SDL_Rect res;

    const SDL_Color col = { 0, 0, 0, 0 };
    text_surface s(line, font_size, col, style);

    res.w = s.width();
    res.h = s.height();
    res.x = res.y = 0;

    cache.insert(std::pair<std::string,SDL_Rect>(line,res));
    return res;
}

}
